from fake_useragent import UserAgent
from aiohttp import ClientSession
import PySimpleGUI as sg
from pathlib import *
import requests
import aiofiles
import fnmatch
import asyncio
import aiohttp
import re
import os


# 获取查询城市对应的编码
def getDictInfo():
    ua = UserAgent()

    headers = {
        'User-Agent': ua.random
    }

    response = requests.get('https://weather.cma.cn/api/map/weather/1?t=1682856635126', headers=headers)

    response_json = response.json()

    dictInfo = {}

    for i in range(2428):
        code = response_json['data']['city'][i][0]
        address = response_json['data']['city'][i][1]
        dictInfo[address] = code

    return dictInfo


# 获取天气信息
def getWeatherInfo(number):
    listInfo = [][:59]

    ua = UserAgent()

    headers = {
        'User-Agent': ua.random,
        'Referer': f'https://weather.cma.cn/web/weather/{number}.html'
    }
    response = requests.get(f'https://weather.cma.cn/web/weather/{number}.html', headers=headers)

    response.encoding = 'UTF-8'

    response = response.text

    obj = re.compile(r'<div class="day-item">(?P<date>.*?)<br>(?P<Date>.*?)</div>'
                     r'.*?<img src="(?P<img>.*?)">.*?<div class="day-item">(?P<weather>.*?)</div>'
                     r'.*?<div class="day-item">(?P<wind>.*?)</div>'
                     r'.*?<div class="day-item">(?P<windPower>.*?)</div>'
                     r'.*?<div class="high">(?P<high>.*?)</div>'
                     r'.*?<div class="low">(?P<low>.*?)</div>'
                     r'.*?<img src="(?P<img2>.*?)">.*?</div>'
                     r'.*?<div class="day-item">(?P<weather2>.*?)</div>'
                     r'.*?<div class="day-item">(?P<wind2>.*?)</div>'
                     r'.*?div class="day-item">(?P<windPower2>.*?)</div>', re.S)

    result = obj.finditer((response))

    for item in result:
        dic = item.groupdict()
        dic['date'] = dic['date'].strip()
        dic['Date'] = dic['Date'].strip()
        dic['img'] = 'https://weather.cma.cn/' + dic['img']
        urls.append(dic['img'])
        dic['weather'] = dic['weather'].strip()
        dic['wind'] = dic['wind'].strip()
        dic['windPower'] = dic['windPower'].strip()
        dic['high'] = dic['high'].strip()
        dic['low'] = dic['low'].strip()
        dic['img2'] = 'https://weather.cma.cn/' + dic['img2']
        urls.append(dic['img2'])
        dic['weather2'] = dic['weather2'].strip()
        dic['wind2'] = dic['wind2'].strip()
        dic['windPower2'] = dic['windPower2'].strip()

        for i in dic.values():
            listInfo.append(i)

    return listInfo


# 删除天气图片
def removeFile():
    for file in Path('.').iterdir():
        if fnmatch.fnmatch(file, 'image_*.png'):
            os.remove(file)


async def request(session: ClientSession, url: str):
    ua = UserAgent()
    headers = {
        'User-Agent': ua.random
    }
    async with session.get(url, headers=headers) as result:
        return await result.content.read()


async def main():
    async with aiohttp.ClientSession() as session:
        requests = [request(session, url) for url in urls]
        results = await asyncio.gather(*requests)
        return results


async def write():
    for i, imagedata in enumerate(imageDatas):
        filename = f"image_{i + 1}.png"
        async with aiofiles.open(filename, "wb") as file:
            await file.write(imagedata)
            filePath = os.path.abspath(f"image_{i + 1}.png")
            path.append(filePath)


dictInfo = getDictInfo()
sg.theme("LightBrown")
sg.set_options(font=('楷体'))
layout = [
    [sg.T('城市：'), sg.In(key='-INTPUT-', expand_x=True, enable_events=True), sg.B('查询'), sg.B('清除')],
    [[sg.T(key=0, pad=(80, 5))] + [sg.T(key=1)] + [sg.Image(key=2, size=(10, 10), pad=(45, 5))] +
     [sg.T(key=3)] + [sg.T(key=4)] + [sg.T(key=5)] + [sg.T(key=6)] + [sg.T(key=7)] + [
         sg.Image(key=8, size=(10, 10), pad=(45, 5))] + [sg.T(key=9)] +
     [sg.T(key=10)] + [sg.T(key=11)]],

    [[sg.T(key=12, pad=(80, 5))] + [sg.T(key=13)] + [sg.Image(key=14, pad=(45, 5))] +
     [sg.T(key=15)] + [sg.T(key=16)] + [sg.T(key=17)] + [sg.T(key=18)] + [sg.T(key=19)] + [
         sg.Image(key=20, pad=(45, 5))] + [sg.T(key=21)] +
     [sg.T(key=22)] + [sg.T(key=23)]],

    [[sg.T(key=24, pad=(80, 5))] + [sg.T(key=25)] + [sg.Image(key=26, pad=(45, 5))] +
     [sg.T(key=27)] + [sg.T(key=28)] + [sg.T(key=29)] + [sg.T(key=30)] + [sg.T(key=31)] + [
         sg.Image(key=32, pad=(45, 5))] + [sg.T(key=33)] +
     [sg.T(key=34)] + [sg.T(key=35)]],

    [[sg.T(key=36, pad=(80, 5))] + [sg.T(key=37)] + [sg.Image(key=38, pad=(45, 5))] +
     [sg.T(key=39)] + [sg.T(key=40)] + [sg.T(key=41)] + [sg.T(key=42)] + [sg.T(key=43)] + [
         sg.Image(key=44, pad=(45, 5))] + [sg.T(key=45)] +
     [sg.T(key=46)] + [sg.T(key=47)]],

    [[sg.T(key=48, pad=(80, 5))] + [sg.T(key=49)] + [sg.Image(key=50, pad=(45, 5))] +
     [sg.T(key=51)] + [sg.T(key=52)] + [sg.T(key=53)] + [sg.T(key=54)] + [sg.T(key=55)] + [
         sg.Image(key=56, pad=(45, 5))] + [sg.T(key=57)] +
     [sg.T(key=58)] + [sg.T(key=59)]]

]

window = sg.Window('天气预报', layout, return_keyboard_events=True).Finalize()
window.Maximize()

while True:
    event, values = window.read()

    if event == '查询':
        urls = []
        path = []
        removeFile()

        # 判断查询的城市是否输入正确的
        if values['-INTPUT-'] in dictInfo:
            codeInt = int(dictInfo[values['-INTPUT-']])
            weatherInfo = getWeatherInfo(codeInt)

            # 异步下载的天气图片完成并完成排序
            imageDatas = asyncio.run(main())

            # 异步写入
            asyncio.run(write())

            # 拼接成想要的数据格式
            it = iter(path)

            for i in range(2, 60, 6):
                weatherInfo[i] = next(it)

            # 更新所有的元素信息
            for i in range(60):
                window[i].update(weatherInfo[i])

        else:
            sg.popup('输入不正确！')
            window['-INTPUT-'].update('')

    if event == '清除':
        removeFile()
        window['-INTPUT-'].update('')
        for i in range(60):
            window[i].update('')

    if event == sg.WINDOW_CLOSED:
        removeFile()
        break
